home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Demo / pdist / client.py next >
Text File  |  1995-12-21  |  4KB  |  159 lines

  1. """RPC Client module."""
  2.  
  3. import sys
  4. import socket
  5. import pickle
  6. import __builtin__
  7. import os
  8.  
  9.  
  10. # Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)
  11. VERBOSE = 1
  12.  
  13.  
  14. class Client:
  15.     
  16.     """RPC Client class.  No need to derive a class -- it's fully generic."""
  17.     
  18.     def __init__(self, address, verbose = VERBOSE):
  19.         self._pre_init(address, verbose)
  20.         self._post_init()
  21.     
  22.     def _pre_init(self, address, verbose = VERBOSE):
  23.         if type(address) == type(0):
  24.             address = ('', address)
  25.         self._address = address
  26.         self._verbose = verbose
  27.         if self._verbose: print "Connecting to %s ..." % repr(address)
  28.         self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  29.         self._socket.connect(address)
  30.         if self._verbose: print "Connected."
  31.         self._lastid = 0 # Last id for which a reply has been received
  32.         self._nextid = 1 # Id of next request
  33.         self._replies = {} # Unprocessed replies
  34.         self._rf = self._socket.makefile('r')
  35.         self._wf = self._socket.makefile('w')
  36.     
  37.     def _post_init(self):
  38.         self._methods = self._call('.methods')
  39.     
  40.     def __del__(self):
  41.         self._close()
  42.     
  43.     def _close(self):
  44.         if self._rf: self._rf.close()
  45.         self._rf = None
  46.         if self._wf: self._wf.close()
  47.         self._wf = None
  48.         if self._socket: self._socket.close()
  49.         self._socket = None
  50.     
  51.     def __getattr__(self, name):
  52.         if name in self._methods:
  53.             method = _stub(self, name)
  54.             setattr(self, name, method) # XXX circular reference
  55.             return method
  56.         raise AttributeError, name
  57.     
  58.     def _setverbose(self, verbose):
  59.         self._verbose = verbose
  60.     
  61.     def _call(self, name, *args):
  62.         return self._vcall(name, args)
  63.     
  64.     def _vcall(self, name, args):
  65.         return self._recv(self._vsend(name, args))
  66.     
  67.     def _send(self, name, *args):
  68.         return self._vsend(name, args)
  69.     
  70.     def _send_noreply(self, name, *args):
  71.         return self._vsend(name, args, 0)
  72.     
  73.     def _vsend_noreply(self, name, args):
  74.         return self._vsend(name, args, 0)
  75.     
  76.     def _vsend(self, name, args, wantreply = 1):
  77.         id = self._nextid
  78.         self._nextid = id+1
  79.         if not wantreply: id = -id
  80.         request = (name, args, id)
  81.         if self._verbose > 1: print "sending request: %s" % repr(request)
  82.         wp = pickle.Pickler(self._wf)
  83.         wp.dump(request)
  84.         return id
  85.     
  86.     def _recv(self, id):
  87.         exception, value, rid = self._vrecv(id)
  88.         if rid != id:
  89.             raise RuntimeError, "request/reply id mismatch: %d/%d" % (id, rid)
  90.         if exception is None:
  91.             return value
  92.         x = exception
  93.         if hasattr(__builtin__, exception):
  94.             x = getattr(__builtin__, exception)
  95.         elif exception in ('posix.error', 'mac.error'):
  96.             x = os.error
  97.         if x == exception:
  98.             exception = x
  99.         raise exception, value        
  100.     
  101.     def _vrecv(self, id):
  102.         self._flush()
  103.         if self._replies.has_key(id):
  104.             if self._verbose > 1: print "retrieving previous reply, id = %d" % id
  105.             reply = self._replies[id]
  106.             del self._replies[id]
  107.             return reply
  108.         aid = abs(id)
  109.         while 1:
  110.             if self._verbose > 1: print "waiting for reply, id = %d" % id
  111.             rp = pickle.Unpickler(self._rf)
  112.             reply = rp.load()
  113.             del rp
  114.             if self._verbose > 1: print "got reply: %s" % repr(reply)
  115.             rid = reply[2]
  116.             arid = abs(rid)
  117.             if arid == aid:
  118.                 if self._verbose > 1: print "got it"
  119.                 return reply
  120.             self._replies[rid] = reply
  121.             if arid > aid:
  122.                 if self._verbose > 1: print "got higher id, assume all ok"
  123.                 return (None, None, id)
  124.     
  125.     def _flush(self):
  126.         self._wf.flush()
  127.  
  128.  
  129. from security import Security
  130.  
  131.  
  132. class SecureClient(Client, Security):
  133.  
  134.     def __init__(self, *args):
  135.         import string
  136.         apply(self._pre_init, args)
  137.         Security.__init__(self)
  138.         self._wf.flush()
  139.         line = self._rf.readline()
  140.         challenge = string.atoi(string.strip(line))
  141.         response = self._encode_challenge(challenge)
  142.         line = `long(response)`
  143.         if line[-1] in 'Ll': line = line[:-1]
  144.         self._wf.write(line + '\n')
  145.         self._wf.flush()
  146.         self._post_init()
  147.  
  148. class _stub:
  149.     
  150.     """Helper class for Client -- each instance serves as a method of the client."""
  151.     
  152.     def __init__(self, client, name):
  153.         self._client = client
  154.         self._name = name
  155.     
  156.     def __call__(self, *args):
  157.         return self._client._vcall(self._name, args)
  158.  
  159.